﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using FluentData;
using Core;

namespace Data
{
    public class BaseService<T>
    {
        private IDbContext _Db;
        public IDbContext Db {
            get {
                if (_Db == null)
                    _Db = new DbContext().ConnectionStringName("DefaultConnection", new SqlServerProvider());
                _Db.IgnoreIfAutoMapFails(true);
                return _Db;
            }
        }

        public T GetModel(ParamQuery pq) {
            var sql = string.Format(@"Select {0}.* From {0} Where {1}", TableName, pq.Where);
            return Db.Sql(sql).QuerySingle<T>();
        }

        public List<T> GetModels(ParamQuery pq = null) {
            var sql = string.Format(@"Select {0}.* From {0} {1}", TableName, pq == null ? "" : " Where " + pq.Where);
            if (pq!=null && !string.IsNullOrEmpty(pq.OrderBy)) sql = string.Format("{0} Order By {1}", sql, pq.OrderBy);
            return Db.Sql(sql).QueryMany<T>();
        }

        public List<dynamic> GetDynamicList() {
            var sql = string.Format(@"Select {0}.* From {0} Where {1}", TableName, "");
            return Db.Sql(sql).QueryMany<dynamic>();
        }

        public dynamic GetDynamicList(ParamQuery pq) {
            if ((pq.Select + "").Trim() == "") pq.Select = "*";
            if ((pq.From + "").Trim() == "") pq.From = this.TableName;
            if ((pq.Where + "").Trim() == "") pq.Where = " 1=1 ";

            var ib = Db.Select<dynamic>(pq.Select).From(pq.From).Where(pq.Where);
            if (!string.IsNullOrEmpty(pq.OrderBy.Trim())) {
                ib.OrderBy(pq.OrderBy);
            }
            return new { rows = ib.QueryMany() };
        }

        public dynamic GetDynamicListWithPaging(ParamQuery pq) {
            var rows = Db.Select<dynamic>(pq.Select).From(pq.From).Where(pq.Where).OrderBy(pq.OrderBy).Paging(pq.PageNumber, pq.PageSize).QueryMany();
            var total = Db.Select<int>("Count(0)").From(pq.From).Where(pq.Where).QuerySingle();
            return new { rows = rows, total = total };
        }

        public string TableName {
            get {
                string name = "";
                var filed = typeof(T).GetField("TableName");
                if (filed != null)
                    name = filed.GetValue(null) + "";

                if (string.IsNullOrEmpty(name))
                    name = typeof(T).Name;
                return name;
            }
        }

        public int Insert(ParamBase param) {
            return this.Insert(param, null);
        }

        public int Insert(ParamBase param, IDbContext db) {
            if (db == null) db = Db;
            var ib = db.Insert(param.Table);
            param.FieldInserts.ForEach(x => {
                if (!string.IsNullOrEmpty(x.Name) && !string.IsNullOrEmpty(x.Value))
                    ib.Column(x.Name, x.Value);
            });

            return ib.Execute();
        }

        public int Update(ParamBase param) {
            return Update(param, null);
        }
        public int Update(ParamBase param, IDbContext db) {
            if (string.IsNullOrEmpty(param.Table)) param.Table = this.TableName;
            if (db == null) db = Db;
            var ib = db.Update(param.Table);
            param.FieldUpdates.ForEach(x => {
                if (!string.IsNullOrEmpty(x.Name) && !string.IsNullOrEmpty(x.Value))
                    ib.Column(x.Name, x.Value);
            });
            param.FieldWheres.ForEach(x => {
                ib.Where(x.Name, x.Value);
            });
            return ib.Execute();
        }


        public int Delete(ParamBase param) {
            return this.Delete(param, null);
        }
        public int Delete(ParamBase param, IDbContext db) {
            if (string.IsNullOrEmpty(param.Table)) param.Table = this.TableName;
            if (db == null) db = Db;
            var delBuilder = db.Delete(param.Table);
            param.FieldWheres.ForEach(x => {
                delBuilder.Where(x.Name, x.Value);
            });
            return delBuilder.Execute();
        }

        public bool Edit(List<ParamBase> paramList) {
            using (var db = Db.UseTransaction(true)) {
                foreach (var p in paramList) {
                    switch (p.Operator) {
                        case OperateType.Insert:
                            this.Insert(p, db);
                            break;
                        case OperateType.Update:
                            this.Update(p, db);
                            break;
                        case OperateType.Delete:
                            this.Delete(p, db);
                            break;
                        default:
                            break;
                    }
                }
                db.Commit();
            }
            return true;
        }

    }
}
